﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using Red.Controls.ViewModels;
using Red.Core.Extensions;

namespace Red.Controls.Utils
{
    public sealed class IconPickerCommandParam : Freezable
    {
        #region Implemented Methods

        // IconPickerCommandParam inherits from Freezable so that we inherit the DataContext of the parent:
        // http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
        protected override Freezable CreateInstanceCore()
        {
            return new IconPickerCommandParam();
        }

        #endregion Implemented Methods

        #region Properties

        public static readonly DependencyProperty ParentProperty = DependencyProperty.Register( "Parent", typeof( object ), typeof( IconPickerCommandParam ) );
        public static readonly DependencyProperty TargetTextBoxProperty = DependencyProperty.Register( "TargetTextBox", typeof( object ), typeof( IconPickerCommandParam ) );

        public object Parent
        {
            get { return GetValue( ParentProperty ); }
            set { SetValue( ParentProperty, value ); }
        }


        public object TargetTextBox
        {
            get { return GetValue( TargetTextBoxProperty ); }
            set { SetValue( TargetTextBoxProperty, value ); }
        }

        #endregion Properties
    }

    [ContentProperty( "SourceDictionaries" )]
    public sealed class IconPickerCommand : ICommand
    {
        public ObservableCollection<Uri> SourceDictionaries { get; set; } = new ObservableCollection<Uri>();
        public List<CommandPaletteItem> items { get; set; } = new List<CommandPaletteItem>();

        public string SelectedIcon { get; private set; }

        #region Events

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        #endregion Events

        public IconPickerCommand()
        {
            SourceDictionaries.CollectionChanged += SourceDictionaries_CollectionChanged;
        }

        private void AddDictionary( List<CommandPaletteItem> items, Uri source )
        {
            ResourceDictionary iconDictionary;

            try
            {
                iconDictionary = new ResourceDictionary() { Source = source };
            }
            catch ( System.IO.IOException )
            {
                System.Diagnostics.Debug.Print( $"Could not find icon dictionary {source}" );
                return;
            }

            IEnumerable<object> resources = iconDictionary.Keys.Cast<object>().Where( key => iconDictionary[ key ] is Canvas ).Select( key => key ).OrderBy( s => s );

            foreach ( object resource in resources )
            {
                string name = resource.ToString();

                CommandPaletteItem<string> item = new CommandPaletteItem<string>( name )
                {
                    Name = name,
                    Comment = name,
                    IconCanvas = iconDictionary[ name ] as Canvas
                };

                item.Click += ( object sender, string selected ) => { SelectedIcon = selected; };

                items.Add( item );
            }
        }

        private void SourceDictionaries_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
        {
            if( e.Action == NotifyCollectionChangedAction.Add )
            {
                foreach( Uri uri in e.NewItems )
                {
                    AddDictionary( items, uri );
                }
            }
        }

        #region Interface Methods

        public bool CanExecute( object sender )
        {
            return true;
        }

        public void Execute( object parameter )
        {
            var param = parameter as IconPickerCommandParam;
            if ( param == null )
                return;

            CommandPalette iconPicker = new CommandPalette();
            iconPicker.Items = items;
            iconPicker.SetPositionRelativeTo( param.Parent as System.Windows.Media.Visual );
            iconPicker.ShowDialog();

            var property = param.TargetTextBox.GetType().GetProperty( "Text" );
            property.SetValue( param.TargetTextBox, iconPicker.SelectedItem.Name );
        }

        #endregion Interface Methods
    }
}
